#pragma once
#include <unistd.h>
#include <sys/poll.h>
#include "Socket.hpp"

class PoLLServer
{
    const static uint16_t DEFAULT_SERVER_PORT = 8080;
    const static int DEFAULT_POLL_NUM = 1024;
    const static int DEFAULT_TIMEOUT = 1000;
    const static int NULL_FD = -1;

public:
    static PoLLServer *GetInstance()
    {
        if (_self == nullptr)
        {
            _self = new PoLLServer();
        }
    }
    void Run()
    {
        // 默认第一位为listen套接字
        _pollfds[0].fd = _listensock;
        _pollfds[0].events = POLLIN;
        // 开始执行运行服务器
        while (true)
        {
            // 将网络流监听文件描述符加入Poll中管理
            switch (poll(_pollfds, _pollfd_num, _timeout))
            {
            case 0:
                break;
            case -1:
                break;
            default:
                for (int i = 0; i < _pollfd_num; i++)
                {
                    if (_pollfds[i].fd == NULL_FD || _pollfds[i].revents == 0)
                        continue;
                    // 执行业务处理HanderEvent
                    HanderEvent(i);
                }
                break;
            }
        }
    }
    ~PoLLServer()
    {
        if (_self)
        {
            delete _self;
            _self = nullptr;
        }
        if (_pollfds)
        {
            delete _pollfds;
            _pollfds = nullptr;
        }
    }

private:
    void HanderEvent(int index)
    {
        if (index == 0)
        {
            if (_pollfds[index].revents == POLLIN)
                ServerAccept();
        }
        else
        {
            if (_pollfds[index].revents == POLLIN)
                Recvive(index);
            // else if(_pollfds[index].revents == POLLOUT)
            // Send(i);
        }
    }
    void ServerAccept()
    {
        std::string ip;
        uint16_t port;
        int accept_errno;
        int sock = Socket::Accept(_pollfds[0].fd, &ip, &port, &accept_errno);
        std::cout << "get a link ip:" << ip << " port:" << port << std::endl;
        // 将与client交流的文件描述符存入poll中
        for (int i = 0; i <= _pollfd_num; i++)
        {
            if (_pollfds[i].fd == NULL_FD)
            {
                _pollfds[i].fd = sock;
                _pollfds[i].events = POLLIN;
                break;
            }
            if (i == _pollfd_num)
            {
                // 扩容 OR 抛弃
                std::cout << "pollServer 满载" << std::endl;
                close(sock);
            }
        }
    }
    void Recvive(int index)
    {
        char buffer[1024];
        int num = recv(_pollfds[index].fd, buffer, sizeof(buffer) - 1, 0);
        if (num < 0)
        {
            std::cerr << "client errno" << std::endl;
            // 将poll设置不在关心该fd
            _pollfds[index].fd = NULL_FD;
            _pollfds[index].events = _pollfds[index].revents = 0;
            close(_pollfds[index].fd);
        }
        else if (num == 0)
        {
            std::cout << "client close" << std::endl;
            // 将poll设置不在关心该fd
            _pollfds[index].fd = NULL_FD;
            _pollfds[index].events = _pollfds[index].revents = 0;
            close(_pollfds[index].fd);
        }
        //没有问题获取client的信息
        else
        {
            buffer[num] = 0;
            std::cout << "client:" << buffer << std::endl;
        }
    }

    PoLLServer(int port_num = DEFAULT_POLL_NUM, uint16_t server_port = DEFAULT_SERVER_PORT) : _server_port(server_port), _pollfd_num(port_num)
    {
        _pollfds = new pollfd[_pollfd_num];
        for (int i = 0; i < _pollfd_num; i++)
        {
            _pollfds[i].fd = NULL_FD;
            _pollfds[i].revents = 0;
        }
        // 创建网络流
        _listensock = Socket::Sock();
        Socket::Bind(_listensock, _server_port);
        Socket::Listen(_listensock);

        _timeout = DEFAULT_TIMEOUT;
    }

    PoLLServer(const PoLLServer &poLLServer) = delete;

private:
    static PoLLServer *_self;
    int _listensock;
    uint16_t _server_port;
    pollfd *_pollfds;
    int _pollfd_num;
    int _timeout;
};
PoLLServer *PoLLServer::_self = nullptr;
